define(["jquery", "bootstrap", "backend", "table", "form"], function ($, undefined, Backend, Table, Form) {
    var Controller = {
        index: function () {
            var CalColors = { ongoing: '#F5A623', completed: '#2ECC71', upcoming: '#3498DB' };
            var CurrentMonth = null;


            function ensureCourseCalendar(){
                if($('#course-calendar').length===0){
                    var html='';
                    html+='<div id="course-calendar" class="panel panel-default" style="margin-top:10px">';
                    html+='<div class="panel-heading">';
                    html+='<div class="row">';
                    html+='<div class="col-xs-4">';
                    html+='<div class="btn-group">';
                    html+='<a class="btn btn-default" id="cal-prev"><i class="fa fa-angle-left"></i></a>';
                    html+='<span id="cal-title" class="btn btn-default disabled" style="min-width:160px"></span>';
                    html+='<a class="btn btn-default" id="cal-next"><i class="fa fa-angle-right"></i></a>';
                    html+='</div>';
                    html+='</div>';
                    html+='<div class="col-xs-8" id="cal-legend" style="text-align:right"></div>';
                    html+='</div>';
                    html+='</div>';
                    html+='<div class="panel-body" id="cal-grid"></div>';
                    html+='</div>';
                    var $container=$('#course');
                    var $anchor=$container.find('#form-course-filter');
                    if($anchor.length){ $anchor.after(html); } else { $container.append(html); }
                    $('#cal-prev').on('click', function(){ shiftMonth(-1); });
                    $('#cal-next').on('click', function(){ shiftMonth(1); });
                }
            }

            function monthStartEnd(d){
                var y=d.getFullYear(), m=d.getMonth();
                var start=new Date(y,m,1);
                var end=new Date(y,m+1,0);
                return {start:start,end:end};
            }

            function setMonthFromRange(){
                var dr = $('#course-date_range').val() || '';
                var ds = '', de = '';
                if (dr && dr.indexOf(' - ') > -1) { var arr = dr.split(' - '); ds = arr[0]; de = arr[1]; }
                else { ds = $('#course-date_start').val(); de = $('#course-date_end').val(); }
                var base = ds ? new Date(ds+'T00:00:00') : new Date();
                base.setDate(1);
                CurrentMonth = base;
                renderCalendarMonth(CurrentMonth);
                loadCourseCalendar();
            }

            function shiftMonth(delta){
                if(!CurrentMonth){ CurrentMonth = new Date(); CurrentMonth.setDate(1); }
                CurrentMonth.setMonth(CurrentMonth.getMonth()+delta);
                renderCalendarMonth(CurrentMonth);
                loadCourseCalendar();
            }

            function renderCalendarMonth(d){
                var me = monthStartEnd(d);
                var y = d.getFullYear();
                var m = d.getMonth()+1;
                var title = y+'-'+(m<10?('0'+m):m);
                $('#cal-title').text(title);
                var first = me.start;
                var last = me.end;
                var startDay = first.getDay();
                var days = last.getDate();
                var weeks = [];
                var day = 1;
                for(var r=0;r<6;r++){
                    var row = '<div class="row" style="margin-bottom:6px">';
                    for(var c=0;c<7;c++){
                        var cell = '';
                        if(r===0 && c<startDay){ cell = '<div class="col-xs-1" style="min-height:40px"></div>'; }
                        else if(day<=days){
                            var mm = m<10?('0'+m):(''+m);
                            var dd = day<10?('0'+day):(''+day);
                            var key = y+'-'+mm+'-'+dd;
                            cell = '<div class="col-xs-1" style="min-height:40px"><div>'+day+'</div><div class="dots" data-date="'+key+'"></div></div>';
                            day++;
                        } else { cell = '<div class="col-xs-1" style="min-height:40px"></div>'; }
                        row += cell;
                    }
                    row += '</div>';
                    weeks.push(row);
                }
                $('#cal-grid').html(weeks.join(''));
                $('#cal-legend').html('');
            }

            function combineCalendarData(data){
                var list=[];
                if(data && data.school){ for(var i=0;i<data.school.length;i++){ list.push(data.school[i]); } }
                if(data && data.community){ for(var i=0;i<data.community.length;i++){ list.push(data.community[i]); } }
                if(data && data.external){ for(var i=0;i<data.external.length;i++){ list.push(data.external[i]); } }
                return list;
            }

            function renderDotsByDay(list){
                var counts={ ongoing:0, completed:0, upcoming:0 };
                for(var i=0;i<list.length;i++){
                    var d=list[i];
                    var status=(d.status||'').toLowerCase();
                    if(!CalColors[status]) status='upcoming';
                    counts[status]=(counts[status]||0)+1;
                    var key=d.date;
                    var $dots=$('.dots[data-date="'+key+'"]').first();
                    if($dots.length){
                        var color=CalColors[status]||'#999';
                        var span='<span style="display:inline-block;width:8px;height:8px;background:'+color+';border-radius:50%;margin-right:4px"></span>';
                        $dots.append(span);
                    }
                }
                var legend='';
                legend+='<span style="margin-right:10px"><span style="display:inline-block;width:10px;height:10px;background:'+CalColors.completed+';border-radius:50%;margin-right:4px"></span>'+__('已完成')+counts.completed+'</span>';
                legend+='<span style="margin-right:10px"><span style="display:inline-block;width:10px;height:10px;background:'+CalColors.ongoing+';border-radius:50%;margin-right:4px"></span>'+__('进行中')+counts.ongoing+'</span>';
                legend+='<span><span style="display:inline-block;width:10px;height:10px;background:'+CalColors.upcoming+';border-radius:50%;margin-right:4px"></span>'+__('未开始')+counts.upcoming+'</span>';
                $('#cal-legend').html(legend);
            }

            function loadCourseCalendar(){
                if(!CurrentMonth){ CurrentMonth=new Date(); CurrentMonth.setDate(1); }
                var me = monthStartEnd(CurrentMonth);
                var ds = me.start.getFullYear()+'-'+((me.start.getMonth()+1<10)?('0'+(me.start.getMonth()+1)):(me.start.getMonth()+1))+'-01';
                var de = me.end.getFullYear()+'-'+((me.end.getMonth()+1<10)?('0'+(me.end.getMonth()+1)):(me.end.getMonth()+1))+'-'+((me.end.getDate()<10)?('0'+me.end.getDate()):me.end.getDate());
                $.getJSON('/ysapi/v1/course/calendar', { date_start: ds, date_end: de }, function(res){
                    var list=[];
                    if(res && res.code===200 && res.data){ list = combineCalendarData(res.data); }
                    renderDotsByDay(list);
                });
            }

            $(document).on('shown.bs.tab', 'a[href="#course"]', function(){
                ensureCourseCalendar();
                setMonthFromRange();
            });

            $(document).on('change', '#course-date_range,#course-date_start,#course-date_end', function(){
                setMonthFromRange();
            });

            Table.api.init({
                extend: {index_url: "statistics/index"}
            });
            var tableBasic = $("#table-basic");
            tableBasic.bootstrapTable({
                data: [],
                columns: [
                    {field: "label", title: __("自定义")},
                    {field: "school_count", title: __("学校(个)")},
                    {field: "class_count", title: __("班级(个)")},
                    {field: "offline_people", title: __("线下(人)")},
                    {field: "online_people", title: __("线上(人)")}
                ],
                search: false,
                pagination: false,
                undefinedText: "",
                striped: true,
                toolbar: '#basic-toolbar'
            });
            var tableTeaching = $("#table-teaching");
            tableTeaching.bootstrapTable({
                data: [],
                columns: [
                    {field: "item", title: __("汇总项")},
                    {field: "value", title: __("数值")}
                ],
                search: false,
                pagination: false,
                undefinedText: "",
                striped: true,
                toolbar: '#teaching-toolbar'
            });
            var tableCourse = $("#table-course");
            tableCourse.bootstrapTable({
                data: [],
                columns: [
                    {field: "date", title: __("日期")},
                    {field: "name", title: __("课程名称")},
                    {field: "school", title: __("学校")},
                    {field: "class", title: __("班级")}
                ],
                search: false,
                undefinedText: "",
                striped: true,
                toolbar: '#course-toolbar'
            });

            var CourseCalState = {year: null, month: null};
            var CalColors = {done: '#2ECC71', overdue: '#9E9E9E', running: '#F5A623', pending: '#3498DB', unfinished: '#F1C40F'};
            function ensureCourseCalendar(){ if($('#course-calendar').length===0){ var html=''; html+='<div id="course-calendar" class="panel panel-default" style="margin-top:10px">'; html+='<div class="panel-heading">'; html+='<div class="row">'; html+='<div class="col-xs-4">'; html+='<div class="btn-group">'; html+='<a class="btn btn-default" id="cal-prev"><i class="fa fa-angle-left"></i></a>'; html+='<span id="cal-title" class="btn btn-default disabled" style="min-width:160px"></span>'; html+='<a class="btn btn-default" id="cal-next"><i class="fa fa-angle-right"></i></a>'; html+='</div>'; html+='</div>'; html+='<div class="col-xs-8" id="cal-legend" style="text-align:right"></div>'; html+='</div>'; html+='</div>'; html+='<div class="panel-body" id="cal-grid"></div>'; html+='</div>'; var $container=$('#course'); if($container.length){ var $anchor=$container.find('#form-course-filter'); if($anchor.length){ $anchor.after(html); } else { $container.append(html); } $('#cal-prev').on('click', function(){ shiftMonth(-1); }); $('#cal-next').on('click', function(){ shiftMonth(1); }); } } }
            function setMonthFromRange(){ var dr=$('#course-date_range').val()||''; var d=new Date(); if(dr&&dr.indexOf(' - ')>-1){ var a=dr.split(' - ')[0]; var parts=a.split('-'); if(parts.length===3){ d=new Date(parseInt(parts[0],10), parseInt(parts[1],10)-1, 1); } } CourseCalState.year=d.getFullYear(); CourseCalState.month=d.getMonth()+1; }
            function shiftMonth(delta){ var y=CourseCalState.year, m=CourseCalState.month; m+=delta; if(m<=0){ m=12; y--; } else if(m>12){ m=1; y++; } CourseCalState.year=y; CourseCalState.month=m; renderCalendarMonth(); loadCourseCalendar(); }
            function monthStartEnd(y,m){ var start=new Date(y, m-1, 1); var end=new Date(y, m, 0); function fmt(dt){ var mm=dt.getMonth()+1; var dd=dt.getDate(); return dt.getFullYear()+'-'+(mm<10?'0'+mm:mm)+'-'+(dd<10?'0'+dd:dd); } return {start: fmt(start), end: fmt(end)}; }
            function renderCalendarMonth(){ var y=CourseCalState.year, m=CourseCalState.month; $('#cal-title').text(y+'年'+m+'月'); var first=new Date(y, m-1, 1); var startWeek=first.getDay(); var days=new Date(y, m, 0).getDate(); var html=''; html+='<div class="row" style="margin-bottom:8px;text-align:center">'; var weekdays=['周日','周一','周二','周三','周四','周五','周六']; for(var i=0;i<7;i++){ html+='<div class="col-xs-1" style="width:14.28%"><b>'+__(weekdays[i])+'</b></div>'; } html+='</div>'; html+='<div>'; var cell=0; var i; html+='<div class="row">'; for(i=0;i<startWeek;i++){ html+='<div class="col-xs-1" style="width:14.28%;height:60px"></div>'; cell++; } for(i=1;i<=days;i++){ if(cell%7===0&&cell>0){ html+='</div><div class="row">'; } var day= i<10?('0'+i):(''+i); var mm = m<10?('0'+m):(''+m); var key = y+'-'+mm+'-'+day; html+='<div class="col-xs-1" style="width:14.28%;height:60px;border:1px solid #eee;border-right:none;border-bottom:none;position:relative;padding:4px">'; html+='<div style="position:absolute;top:4px;left:6px">'+i+'</div>'; html+='<div class="dots" data-date="'+key+'" style="position:absolute;bottom:6px;left:6px;right:6px;height:14px"></div>'; html+='</div>'; cell++; } while(cell%7!==0){ html+='<div class="col-xs-1" style="width:14.28%;height:60px"></div>'; cell++; } html+='</div>'; html+='</div>'; $('#cal-grid').html(html); }
            function statusOfLesson(ts){ var now=new Date(); var t=new Date(ts.replace(/\s/,'T')); var diff=(t.getTime()-now.getTime())/3600000; if(diff<-2) return 'done'; if(diff<-0.1) return 'running'; if(diff<-24) return 'overdue'; if(diff>0) return 'pending'; return 'unfinished'; }
            function renderDotsByDay(data){ var counts={done:0,overdue:0,running:0,pending:0,unfinished:0}; for(var i=0;i<data.length;i++){ var d=data[i]; var st=d.start_time||d.date||d.start||''; if(!st) continue; var status=statusOfLesson(st); counts[status]++; var dt=new Date(st.replace(/\s/,'T')); var y=dt.getFullYear(); var m=dt.getMonth()+1; var day=dt.getDate(); var mm=m<10?('0'+m):(''+m); var dd=day<10?('0'+day):(''+day); var key=y+'-'+mm+'-'+dd; var $dots=$('.dots[data-date="'+key+'"]').first(); if($dots.length){ var color=CalColors[status]||'#999'; var span='<span style="display:inline-block;width:8px;height:8px;background:'+color+';border-radius:50%;margin-right:4px"></span>'; $dots.append(span); } } var legendHtml=''; legendHtml+='<span style="margin-right:10px"><span style="display:inline-block;width:10px;height:10px;background:'+CalColors.done+';border-radius:50%;margin-right:4px"></span>'+__('已完成')+counts.done+'</span>'; legendHtml+='<span style="margin-right:10px"><span style="display:inline-block;width:10px;height:10px;background:'+CalColors.overdue+';border-radius:50%;margin-right:4px"></span>'+__('已过期')+counts.overdue+'</span>'; legendHtml+='<span style="margin-right:10px"><span style="display:inline-block;width:10px;height:10px;background:'+CalColors.running+';border-radius:50%;margin-right:4px"></span>'+__('进行中')+counts.running+'</span>'; legendHtml+='<span style="margin-right:10px"><span style="display:inline-block;width:10px;height:10px;background:'+CalColors.pending+';border-radius:50%;margin-right:4px"></span>'+__('未执行')+counts.pending+'</span>'; legendHtml+='<span><span style="display:inline-block;width:10px;height:10px;background:'+CalColors.unfinished+';border-radius:50%;margin-right:4px"></span>'+__('未结束')+counts.unfinished+'</span>';   #cal-legend.html(legendHtml); console.log('[calendar] legend', counts); }
            function loadCourseCalendar(){ ensureCourseCalendar(); if(!CourseCalState.year||!CourseCalState.month){ setMonthFromRange(); } renderCalendarMonth(); var y=CourseCalState.year, m=CourseCalState.month; var se=monthStartEnd(y,m); var st=$('#course-scope_type').val(); var sid=(st==='province')?$('#course-province_id').val():(st==='city')?$('#course-city_id').val():$('#course-school_id').val(); var params={ scope_type: st, scope_id: sid, date_start: se.start, date_end: se.end }; $.getJSON('/ysapi/v1/course/calendar', params, function(res){ var list=[]; if(res && res.code===200 && res.data){ list=res.data; } renderDotsByDay(list); }); }

            function initDatePickers() {
                require(["bootstrap-daterangepicker", "css!../libs/bootstrap-daterangepicker/daterangepicker.css"], function () {
                    var localeOpts = {format: "YYYY-MM-DD", separator: " - ", applyLabel: "确定", cancelLabel: "取消"};
                    $("#c-date_range")
                        .daterangepicker({autoUpdateInput: false, locale: localeOpts})
                        .on("apply.daterangepicker", function (ev, picker) {
                            $(this).val(picker.startDate.format("YYYY-MM-DD") + " - " + picker.endDate.format("YYYY-MM-DD"));
                            loadBasic();
                        })
                        .on("cancel.daterangepicker", function () {
                            $(this).val("");
                            loadBasic();
                        });
                    $("#t-date_range")
                        .daterangepicker({autoUpdateInput: false, locale: localeOpts})
                        .on("apply.daterangepicker", function (ev, picker) {
                            $(this).val(picker.startDate.format("YYYY-MM-DD") + " - " + picker.endDate.format("YYYY-MM-DD"));
                            loadTeaching();
                        })
                        .on("cancel.daterangepicker", function () {
                            $(this).val("");
                            loadTeaching();
                        });
                    $("#course-date_range")
                        .daterangepicker({autoUpdateInput: false, locale: localeOpts})
                        .on("apply.daterangepicker", function (ev, picker) {
                            $(this).val(picker.startDate.format("YYYY-MM-DD") + " - " + picker.endDate.format("YYYY-MM-DD"));
                            loadCourse();
                        })
                        .on("cancel.daterangepicker", function () {
                            $(this).val("");
                            loadCourse();
                        });
                });
                if (Form.events && Form.events.datetimepicker) {
                    Form.events.datetimepicker($(".datetimepicker"));
                }
            }

            function fillOptions($select, list, placeholder) {
                $select.empty();
                if (placeholder) {
                    $select.append('<option value="">' + placeholder + '</option>');
                }
                $.each(list, function (i, item) {
                    var id = item.id || item.value || item.ID || item.Id || item.id;
                    var name = item.name || item.text || item.Name || item.title || item.name;
                    $select.append('<option value="' + id + '">' + name + '</option>');
                });
            }

            function loadProvinces(prefix, selected) {
                var d = $.Deferred();
                $.getJSON('/cityarea/cityarea/getAreas', {level: 1, parent_id: 0})
                    .done(function (res) {
                        fillOptions($('#' + prefix + '-province_id'), res || [], '选择省');
                        if (typeof selected !== 'undefined' && selected !== null) {
                            $('#' + prefix + '-province_id').val(selected);
                        }
                        $('#' + prefix + '-city_id').empty();
                        $('#' + prefix + '-district_id').empty();
                        d.resolve();
                    }).fail(function () {
                    d.resolve();
                });
                return d.promise();
            }

            function loadCities(prefix, selected) {
                var d = $.Deferred();
                var pid = $('#' + prefix + '-province_id').val() || 0;
                $.getJSON('/cityarea/cityarea/getAreas', {level: 2, parent_id: pid})
                    .done(function (res) {
                        fillOptions($('#' + prefix + '-city_id'), res || [], '选择市');
                        if (typeof selected !== 'undefined' && selected !== null) {
                            $('#' + prefix + '-city_id').val(selected);
                        }
                        $('#' + prefix + '-district_id').empty();
                        d.resolve();
                    }).fail(function () {
                    d.resolve();
                });
                return d.promise();
            }

            function loadDistricts(prefix, selected) {
                var d = $.Deferred();
                var cid = $('#' + prefix + '-city_id').val() || 0;
                $.getJSON('/cityarea/cityarea/getAreas', {level: 3, parent_id: cid})
                    .done(function (res) {
                        fillOptions($('#' + prefix + '-district_id'), res || [], '选择区县');
                        if (typeof selected !== 'undefined' && selected !== null) {
                            $('#' + prefix + '-district_id').val(selected);
                        }
                        d.resolve();
                    }).fail(function () {
                    d.resolve();
                });
                return d.promise();
            }

            function loadSchools(prefix, selected) {
                var d = $.Deferred();
                var cid = $('#' + prefix + '-city_id').val() || 0;
                var did = $('#' + prefix + '-district_id').val() || 0;
                $.ajax({url: '/school/school/lists', type: 'GET', data: {cityId: cid, districtId: did}})
                    .done(function (data) {
                        try {
                            var json = (typeof data === 'string') ? JSON.parse(data) : data;
                            fillOptions($('#' + prefix + '-school_id'), json.list || [], '选择学校');
                            if (typeof selected !== 'undefined' && selected !== null) {
                                $('#' + prefix + '-school_id').val(selected);
                            }
                        } catch (e) {
                            $('#' + prefix + '-school_id').empty();
                        }
                        d.resolve();
                    }).fail(function () {
                    d.resolve();
                });
                return d.promise();
            }

            function loadBasic() {
                var st = $('#c-scope_type').val();
                var label = '';
                if (st === 'province') {
                    label = $('#c-province_id option:selected').text();
                } else if (st === 'city') {
                    label = $('#c-city_id option:selected').text();
                } else if (st === 'school') {
                    label = $('#c-school_id option:selected').text();
                }
                var scopeId = null;
                if (st === 'province') scopeId = $('#c-province_id').val();
                else if (st === 'city') scopeId = $('#c-city_id').val();
                else if (st === 'school') scopeId = $('#c-school_id').val();
                var dr = $('#c-date_range').val() || '';
                var ds = '', de = '';
                if (dr.indexOf(' - ') > -1) {
                    var arr = dr.split(' - ');
                    ds = arr[0];
                    de = arr[1];
                }
                var params = {
                    scope_type: st,
                    scope_id: scopeId,
                    region_mode: $('#c-region_mode').val(),
                    teach_mode: $('#c-teach_mode').val(),
                    date_start: ds,
                    date_end: de
                };
                $.getJSON('/ysapi/v1/statistics/schoolStats', params, function (res) {
                    var d = (res && res.data) ? res.data : res;
                    var row = {
                        label: label || '',
                        school_count: (d && d.school_count) ? d.school_count : 0,
                        class_count: (d && d.class_count) ? d.class_count : 0,
                        offline_people: (d && d.offline_people) ? d.offline_people : 0,
                        online_people: (d && d.online_people) ? d.online_people : 0
                    };
                    tableBasic.bootstrapTable('refreshOptions', {data: [row]});
                    tableBasic.bootstrapTable('resetView');
                });
            }

            function loadTeaching() {
                var items = getSelectedItems();
                var st = $('#t-scope_type').val();
                var scopeId = (st==='province')?$('#t-province_id').val():(st==='city')?$('#t-city_id').val():$('#t-school_id').val();
                var dr = $('#t-date_range').val() || '';
                var ds = '', de = '';
                if (dr.indexOf(' - ') > -1) { var arr = dr.split(' - '); ds = arr[0]; de = arr[1]; }
                getEntitiesByScopeAsync(function(entities){
                    var groups = buildVirtualGrouped(items, entities);
                    renderTeachingChartGrouped(groups);
                });
                var params = {
                    scope_type: st,
                    scope_id: scopeId,
                    region_mode: $('#t-region_mode').val(),
                    teach_mode: $('#t-teach_mode').val(),
                    summary_items: items.join(','),
                    date_start: ds,
                    date_end: de
                };
                var url = $('#t-teach_mode').val() === 'offline' ? '/ysapi/v1/teach/offline' : '/ysapi/v1/teach/online';
                $.getJSON(url, params, function (res) {
                    var rows = [];
                    if (res && res.code === 200 && res.data) { $.each(res.data, function (k, v) { rows.push({item: k, value: v}); }); }
                    if (rows.length === 0) { rows = defaultTeachingRows(); }
                    tableTeaching.bootstrapTable('refreshOptions', {data: rows});
                    tableTeaching.bootstrapTable('resetView');
                });
            }

            var ItemColorsOffline = {
                school: '#1890FF',
                class: '#91CB74',
                people: '#FAC858',
                lessons: '#EE6666',
                checkin: '#73C0DE',
                leave: '#3CA272',
                evaluation: '#9A60B4'
            };
            var ItemLabelsOffline = {
                school: __('学校'),
                class: __('班级'),
                people: __('人数'),
                lessons: __('课数'),
                checkin: __('打卡'),
                leave: __('请假'),
                evaluation: __('评价')
            };
            var ItemColorsOnline = {
                class_people: '#1890FF',
                view_people: '#91CB74',
                view_times: '#FAC858',
                completed_times: '#EE6666',
                courseware_count: '#73C0DE',
                total_duration: '#3CA272',
                avg_duration: '#FC8452',
                participation_rate: '#9A60B4'
            };
            var ItemLabelsOnline = {
                class_people: __('课堂人数'),
                view_people: __('观看人数'),
                view_times: __('观看人次'),
                completed_times: __('完播次数'),
                courseware_count: __('课件数'),
                total_duration: __('总时长'),
                avg_duration: __('人均时长'),
                participation_rate: __('参与率')
            };
            var ItemColors = ItemColorsOffline;
            var ItemLabels = ItemLabelsOffline;
            var OfflineItems = ['school','class','people','lessons','checkin','leave','evaluation'];
            var OnlineItems = ['class_people','view_people','view_times','completed_times','courseware_count','total_duration','avg_duration','participation_rate'];
            var BaseOffline = { school: 16, class: 100, people: 342, lessons: 285, checkin: 260, leave: 20, evaluation: 40 };
            var BaseOnline = { class_people: 60, view_people: 50, view_times: 120, completed_times: 40, courseware_count: 18, total_duration: 8000, avg_duration: 120, participation_rate: 65 };


            function currentTeachMode(){ return $('#t-teach_mode').val()||'offline'; }
            function getSelectedItems() {
                var items = [];
                $('#t-summary_items input:checked').each(function () { items.push($(this).val()); });
                if (items.length === 0) { items = currentTeachMode()==='online' ? OnlineItems.slice(0) : OfflineItems.slice(0); }
                return items;
            }
            function renderSummaryItems(mode){ var items=(mode==='online')?OnlineItems:OfflineItems; var html=''; for(var i=0;i<items.length;i++){ var k=items[i]; var color=(mode==='online')?ItemColorsOnline[k]:ItemColorsOffline[k]; var label=(mode==='online')?ItemLabelsOnline[k]:ItemLabelsOffline[k]; html+='<label class="checkbox-inline"><span style="display:inline-block;width:16px;height:16px;background-color:'+color+';margin-right:8px;border-radius:2px"></span><input type="checkbox" value="'+k+'" checked>'+label+'</label>'; } $('#t-summary_items').html(html); }

            function getEntitiesByScopeAsync(done) {
                var st = $('#t-scope_type').val();
                if (st === 'province') {
                    var pname = $('#t-province_id option:selected').text();
                    if (pname === '广西壮族自治区') {
                        return done(['南宁市', '柳州市', '桂林市']);
                    }
                    return done(['城市A', '城市B', '城市C']);
                }
                if (st === 'city') {
                    var cityName = $('#t-city_id option:selected').text();
                    if (cityName === '南宁市') {
                        return done(['青秀区老年大学', '西乡塘区老年大学', '江南区老年大学']);
                    }
                    return done(['大学A', '大学B', '大学C']);
                }
                var schoolName = $('#t-school_id option:selected').text();
                if (schoolName === '青秀区老年大学') {
                    var sid = $('#t-school_id').val();
                    $.getJSON('/ysapi/v1/statistics/classNamesBySchool', {school_id: sid}, function (res) {
                        var list = [];
                        if (res && res.code === 200 && res.data && res.data.list) {
                            $.each(res.data.list, function (i, c) {
                                list.push(c.name || ('班级' + (i + 1)));
                            });
                        }
                        if (list.length === 0) {
                            list = ['班级1', '班级2', '班级3', '班级4', '班级5', '班级6', '班级7', '班级8'];
                        }
                        done(list);
                    }).fail(function () {
                        done(['班级1', '班级2', '班级3', '班级4', '班级5', '班级6', '班级7', '班级8']);
                    });
                } else {
                    return done(['班级1', '班级2', '班级3', '班级4', '班级5', '班级6', '班级7', '班级8']);
                }
            }

            function buildVirtualGrouped(items, entities){
                var bases = (currentTeachMode()==='online') ? BaseOnline : BaseOffline;
                var groups=[];
                for(var i=0;i<entities.length;i++){
                    var g={ entity:entities[i], values:[] };
                    for(var j=0;j<items.length;j++){
                        var k=items[j]; var b=bases[k]||0; var v=Math.round(b*(0.75+0.12*i));
                        g.values.push({ item:k, value:v });
                    }
                    groups.push(g);
                }
                return groups;
            }

            function renderTeachingChartGrouped(groups){
                var max=0;
                for(var i=0;i<groups.length;i++){ for(var j=0;j<groups[i].values.length;j++){ if(groups[i].values[j].value>max) max=groups[i].values[j].value; } }
                var html='';
                for(var i=0;i<groups.length;i++){
                    html+='<div class="panel panel-default" style="margin-bottom:12px"><div class="panel-heading">'+groups[i].entity+'</div><div class="panel-body">';
                    for(var j=0;j<groups[i].values.length;j++){
                        var v=groups[i].values[j]; var w=max>0?Math.round(v.value/max*100):0;
                        var color=ItemColors[v.item]||'#999'; var label=ItemLabels[v.item]||v.item;
                        html+='<div class="row" style="margin-bottom:8px"><div class="col-xs-2" style="line-height:18px">'+label+'</div><div class="col-xs-10"><div style="display:inline-block;width:'+w+'%;height:16px;background:'+color+';border-radius:2px"></div><span style="margin-left:8px">'+v.value+'</span></div></div>';
                    }
                    html+='</div></div>';
                }
                $('#teaching-chart').html(html);
            }

            function defaultTeachingRows() {
                var items = [];
                $('#t-summary_items input:checked').each(function () { items.push($(this).val()); });
                if (items.length === 0) { items = currentTeachMode()==='online' ? OnlineItems.slice(0) : OfflineItems.slice(0); }
                var vals = (currentTeachMode()==='online') ? BaseOnline : BaseOffline;
                var rows = [];
                for (var i = 0; i < items.length; i++) { var k = items[i]; rows.push({item: k, value: vals[k] || 0}); }
                return rows;
            }

            function renderTeachingChart(rows) {
                var $chart = $('#teaching-chart');
                $chart.empty();
                var max = 0;
                for (var i = 0; i < rows.length; i++) {
                    var v = parseFloat(rows[i].value) || 0;
                    if (v > max) max = v;
                }
                for (var j = 0; j < rows.length; j++) {
                    var r = rows[j];
                    var val = parseFloat(r.value) || 0;
                    var percent = max ? Math.round((val / max) * 100) : 0;
                    var color = ItemColors[r.item] || '#999999';
                    var rowHtml = '' +
                        '<div class="chart-row" style="display:flex;align-items:center;margin:8px 0">'
                        + '<span class="legend" style="min-width:120px;display:flex;align-items:center">'
                        + '<span style="display:inline-block;width:16px;height:16px;background-color:' + color + ';margin-right:8px;border-radius:2px"></span>'
                        + (ItemLabels[r.item] || r.item)
                        + '</span>'
                        + '<div class="progress" style="flex:1;margin:0 10px;height:20px;background:#f0f0f0;border-radius:10px">'
                        + '<div class="progress-bar" role="progressbar" style="width:' + percent + '%;background-color:' + color + ';border-radius:10px"></div>'
                        + '</div>'
                        + '<span class="value" style="min-width:60px;text-align:right">' + val + '</span>'
                        + '</div>';
                    $chart.append(rowHtml);
                }
            }

            function loadCourse() {
                var st = $('#course-scope_type').val();
                var scopeId = null;
                if (st === 'province') scopeId = $('#course-province_id').val();
                else if (st === 'city') scopeId = $('#course-city_id').val();
                else if (st === 'school') scopeId = $('#course-school_id').val();
                var dr = $('#course-date_range').val() || '';
                var ds = '', de = '';
                if (dr.indexOf(' - ') > -1) {
                    var arr = dr.split(' - ');
                    ds = arr[0];
                    de = arr[1];
                }
                var params = {
                    scope_type: st,
                    scope_id: scopeId,
                    teach_mode: $('#course-teach_mode').val(),
                    date_start: ds,
                    date_end: de
                };
                $.getJSON('/ysapi/v1/course/query', params, function (res) {
                    var list = [];
                    if (res && res.code === 200 && res.data) {
                        list = res.data;
                    } else if (Array.isArray(res)) {
                        list = res;
                    }
                    var rows = $.map(list, function (item) {
                        return {
                            date: item.date || item.start_date || item.lesson_date || '',
                            name: item.name || item.title || item.course_name || '',
                            school: item.school || item.school_name || '',
                            class: item.class || item.class_name || item.classes_name || ''
                        };
                    });
                    tableCourse.bootstrapTable('refreshOptions', {data: rows});
                    tableCourse.bootstrapTable('resetView');
                });
            }

            function syncFrom(prefix) {
                var other = ['c', 't', 'course'].filter(function (p) {
                    return p !== prefix;
                });
                var st = $('#' + prefix + '-scope_type').val();
                var pid = $('#' + prefix + '-province_id').val();
                var cid = $('#' + prefix + '-city_id').val();
                var did = $('#' + prefix + '-district_id').val();
                var sid = $('#' + prefix + '-school_id').val();
                var chain = $.Deferred().resolve().promise();
                other.forEach(function (p) {
                    chain = chain.then(function () {
                        $('#' + p + '-scope_type').val(st);
                        return loadProvinces(p, pid)
                            .then(function () {
                                return loadCities(p, cid);
                            })
                            .then(function () {
                                return loadDistricts(p, did);
                            })
                            .then(function () {
                                return loadSchools(p, sid);
                            });
                    });
                });
                chain.then(function () {
                    loadBasic();
                    loadTeaching();
                    loadCourse();
                });
            }

            $(document).on('change', '#c-province_id', function () {
                loadCities('c');
            });
            $(document).on('change', '#c-city_id', function () {
                loadDistricts('c');
                loadSchools('c');
            });
            $(document).on('change', '#c-district_id', function () {
                loadSchools('c');
            });
            $(document).on('change', '#c-scope_type,#c-province_id,#c-city_id,#c-district_id,#c-school_id', function () {
                syncFrom('c');
            });
            $(document).on('change', '#t-province_id', function () {
                loadCities('t');
            });
            $(document).on('change', '#t-city_id', function () {
                loadDistricts('t');
                loadSchools('t');
            });
            $(document).on('change', '#t-district_id', function () {
                loadSchools('t');
            });
            $(document).on('change', '#t-scope_type,#t-province_id,#t-city_id,#t-district_id,#t-school_id', function () {
                syncFrom('t');
            });
            $(document).on('change', '#course-province_id', function () {
                loadCities('course');
            });
            $(document).on('change', '#course-city_id', function () {
                loadDistricts('course');
                loadSchools('course');
            });
            $(document).on('change', '#course-district_id', function () {
                loadSchools('course');
            });
            $(document).on('change', '#course-scope_type,#course-province_id,#course-city_id,#course-district_id,#course-school_id', function () {
                syncFrom('course');
            });
            $(document).on('change', '#course-teach_mode,#course-date_range', function () {
                loadCourse();
                if($(this).attr('id')==='course-date_range'){ setMonthFromRange(); loadCourseCalendar(); }
            });
            $(document).on('change', '#c-teach_mode,#c-date_range,#c-region_mode', function () {
                loadBasic();
            });
            $(document).on('change', '#t-teach_mode', function () {
                var mode = $(this).val()||'offline';
                ItemLabels = (mode==='online') ? ItemLabelsOnline : ItemLabelsOffline;
                ItemColors = (mode==='online') ? ItemColorsOnline : ItemColorsOffline;
                renderSummaryItems(mode);
                loadTeaching();
            });
            $(document).on('change', '#t-region_mode,#t-date_range', function () {
                loadTeaching();
            });
            $(document).on('change', '#t-summary_items input', function () {
                loadTeaching();
            });
            $(document).on('click', '#basic-toolbar .btn-refresh-basic', function () {
                loadBasic();
            });
            $(document).on('click', '#teaching-toolbar .btn-refresh-teaching', function () {
                loadTeaching();
            });
            $(document).on('click', '#course-toolbar .btn-refresh-course', function () {
                loadCourse();
            });
            $(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function () {
                $('#table-basic').bootstrapTable('resetView');
                $('#table-teaching').bootstrapTable('resetView');
                $('#table-course').bootstrapTable('resetView');
            });
            loadProvinces('c');
            loadProvinces('t');
            loadProvinces('course');
            initDatePickers();
            loadBasic();
            renderSummaryItems($('#t-teach_mode').val()||'offline');
            renderTeachingChart(defaultTeachingRows());
            loadTeaching();
            loadCourse();
            setMonthFromRange();
            ensureCourseCalendar();
            renderCalendarMonth();
            loadCourseCalendar();
            Form.api.bindevent($("#add-form"));
            Form.api.bindevent($("#edit-form"));
        },
        add: function () {
            Form.api.bindevent($("#add-form"));
        },
        edit: function () {
            Form.api.bindevent($("#edit-form"));
        }
    };
    return Controller;
});
